/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   Module Name          : com.yaodian100.core.admin.web.acegi.UserDetailsAuthenticationProvider
   Module Description   :

   Date Created      : 2008/4/24
   Original Author   : jeffma
   Team              : Yaodian100
   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   MODIFICATION HISTORY
   ------------------------------------------------------------------------------
   Date Modified       Modified by       Comments
   ------------------------------------------------------------------------------
   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
package com.yaodian100.core.admin.web.acegi;

import java.io.File;
import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.AuthenticationException;
import org.springframework.security.BadCredentialsException;
import org.springframework.security.LockedException;
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
import org.springframework.security.providers.dao.AbstractUserDetailsAuthenticationProvider;
import org.springframework.security.ui.WebAuthenticationDetails;
import org.springframework.security.userdetails.UserDetails;
import org.springframework.security.userdetails.UsernameNotFoundException;

import com.yaodian100.core.admin.entity.User;
import com.yaodian100.core.admin.service.SidebarService;
import com.yaodian100.core.admin.service.UserService;
import com.yaodian100.core.common.exception.CoreException;
import com.yaodian100.core.common.utils.ServerValue;

/**
 * @author jeffma
 */
public class UserDetailsAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {

	/** logger */
	private final Logger logger = LoggerFactory.getLogger(getClass());
	private UserService userService;
	private SidebarService sidebarService;

	/**
	 * @param userService the userService to set
	 */
	public void setUserService(UserService userService) {
		this.userService = userService;
	}

	/**
	 * @param sidebarService the sidebarService to set
	 */
	public void setSidebarService(SidebarService sidebarService) {
		this.sidebarService = sidebarService;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @seeorg.springframework.security.providers.dao. AbstractUserDetailsAuthenticationProvider
	 * #additionalAuthenticationChecks(org .springframework.security.userdetails.UserDetails, org.springframework.security
	 * .providers.UsernamePasswordAuthenticationToken)
	 */
	@Override
	protected void additionalAuthenticationChecks(UserDetails userdetails,
			UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @seeorg.springframework.security.providers.dao.
	 * AbstractUserDetailsAuthenticationProvider#retrieveUser(java.lang.String, org
	 * .springframework.security.providers.UsernamePasswordAuthenticationToken)
	 */
	@Override
	protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication)
			throws AuthenticationException {
		String remoteIp = null;
		try {
			User user = userService.get(username);

			Object detail = authentication.getDetails();
			if (detail instanceof WebAuthenticationDetails) {
				WebAuthenticationDetails webDetail = (WebAuthenticationDetails) detail;
				remoteIp = webDetail.getRemoteAddress();
			}

			if (user == null) {
				logger.error("user not found, username:" + username + ",ip:" + remoteIp);
				throw new UsernameNotFoundException("username:" + username + ",ip:" + remoteIp);
			} else {
				if (!userService.validatePassword(user, authentication.getCredentials().toString())) {
					if (user.getErrorCount() > 5) {
						logger.error("password incorrect, username:" + username + ",ip:" + remoteIp + ",count:"
								+ user.getErrorCount());
					} else {
						logger.warn("password incorrect, username:" + username + ",ip:" + remoteIp);
					}
					throw new BadCredentialsException(messages.getMessage("error.admin.badCredentials", "帐号/密码错误"), user);
				}
			}

			try {
				if (sidebarService != null) {
					String userSidebarPath = ServerValue.getMidHtmlPath() + File.separator + "user" + File.separator
							+ user.getUsername() + ".html";
					File userSidebarFile = new File(userSidebarPath);
					boolean build = false;
					if (userSidebarFile.exists()) {
						Date fileLastModify = new Date(userSidebarFile.lastModified());
						if (fileLastModify.before(sidebarService.getLastModify())) {
							build = true;
						}
						if (fileLastModify.before(user.getModifyDate())) {
							build = true;
						}
					} else {
						build = true;
					}
					if (build) {
						sidebarService.buildSidebar(user);
					}
				}
			} catch (Exception e) {
				logger.error("build sidebar fail", e);
			}

			return user;
		} catch (CoreException e) {
			if ("errors.account.lock".equals(e.getMessage())) {
				logger.error("user locked, username:" + username + ",ip:" + remoteIp);
				throw new LockedException(messages.getMessage(e.getMessage(), "帐号已被锁定, 请联络系统管理员"));
			} else {
				e.printStackTrace();
				logger.error("exception, username:" + username + ",ip:" + remoteIp, e);
				throw new BadCredentialsException(messages.getMessage(e.getMessage(), "帐号/密码错误"));
			}
		}
	}
}
